package com.ams.log.websocket.controller;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.io.FileUtil;
import com.ams.log.websocket.service.AsyncService;
import com.ams.log.websocket.utils.SpringContextUtils;
import com.ams.log.websocket.utils.WebSocketUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.FileSystems;
import java.nio.file.WatchService;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author： 乐哥聊编程(全平台同号)
 */
@Slf4j
@ServerEndpoint(value = "/websocket/log/{userId}/{id}")
@Component
@DependsOn(value = "springContextUtils")
public class OneWebSocket {

    private final AsyncService asyncService = SpringContextUtils.getBean(AsyncService.class);

    /**
     * 绑定服务
     */
    private final static Map<Session, WatchService> concurrentHashMap = new ConcurrentHashMap<>();

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("id") Long id, @PathParam("userId") String userId) throws IOException {
        WatchService watchService = FileSystems.getDefault().newWatchService();
        concurrentHashMap.put(session, watchService);
        // 启动监听
        startLogListener(session, id, userId);
    }

    private void startLogListener(Session session, Long id, String userId) {
        String logPath = fetchLogPath(id);

        // 第一次发送全部信息
        firstLoadFullLogText(session, logPath);


        // 监控的目录
        String filePath = FileUtil.getParent(logPath, 1);
        // 要监控的文件
        String fileName = FileUtil.getName(logPath);
        // 启动异步监听
        asyncService.startListenLogFileAndSendWebsocket(session, filePath, fileName, concurrentHashMap);
    }

    /**
     * 根据业务逻辑获取日志路径，我这边就写死了
     *
     * @param id
     * @return
     */
    private String fetchLogPath(Long id) {
        return "C:\\Users\\leyang5\\Desktop\\log.txt";
    }

    /**
     * 第一次加载发送全部日志
     *
     * @param session
     * @param logPath
     */
    private void firstLoadFullLogText(Session session, String logPath) {
        String logs = FileUtil.readString(logPath, Charset.defaultCharset());
        WebSocketUtil.sendMessage(logs, session);
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) throws IOException {
        concurrentHashMap.get(session).close();
        concurrentHashMap.remove(session);
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
    }

    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误 {}", ExceptionUtil.getRootCauseMessage(error));
        error.printStackTrace();
        concurrentHashMap.remove(session);
    }

}